<script setup lang="ts">
import { useImage } from 'vue-konva'
import { computed, onMounted, onUnmounted, reactive, ref } from 'vue'
import aiSiderInput from './aiSiderInput.vue'
import { mlog } from '@/api'
import { homeStore } from '@/store'

const furnitureImages = ref<any[]>([])
const stageRef = ref()

const [baseImage] = useImage('', 'anonymous')
const [furnitureMixedImage] = useImage('', 'anonymous')

const selectedFurnitureId = ref<string | null>(null)

// 使用 reactive 创建响应式的 stageSize
const stageSize = reactive({
  width: 1024,
  height: 768,
})

const requestCanvasImage = () => {
  if (stageRef.value && stageRef.value.getStage) {
    const stage = stageRef.value.getStage()
    if (stage) {
      const dataURL = stage.toDataURL({
        mimeType: 'image/png',
        quality: 1,
      })
      if (dataURL) {
        const imageArray: any[] = []

        imageArray.push(baseImage.value?.src)
        furnitureImages.value.forEach((furniture) => {
          imageArray.push(furniture.image.src)
        })

        homeStore.setMyData({
          act: 'canvasImage',
          actData: { imageUrl: dataURL, imageArray },
        })
      }
      mlog('requestCanvasImage', dataURL)
    }
  }
}

const loadFurnitureImage = (furniture: any) => {
  const img = new Image()
  img.crossOrigin = 'anonymous'
  img.onload = () => {
    const uniqueId = `${furniture.id}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`
    furnitureImages.value.push({
      id: uniqueId,
      originId: furniture.id,
      image: img,
      x: stageSize.width / 2,
      y: stageSize.height / 2,
      scale: 0.2,
      offsetX: img.width / 2,
      offsetY: img.height / 2,
    })
    selectedFurnitureId.value = uniqueId
  }
  img.onerror = (e) => {
    console.error('图片加载失败:', e)
  }
  img.src = furniture.url
}

const handleFurnitureSelected = (furniture: any) => {
  mlog('handleFurnitureSelected', furniture)
  loadFurnitureImage(furniture)
}

const hcClose = () => {
}

const errorMessage = ref('')

// 画布缩放和平移相关状态
const stageScale = ref(1)
const stagePosition = reactive({
  x: 0,
  y: 0,
})
const isDraggingStage = ref(false)
const lastPointerPosition = reactive({
  x: 0,
  y: 0,
})

const loadBaseImage = (imageUrl: string) => {
  mlog('loadBaseImage', imageUrl)
  errorMessage.value = ''

  if (!imageUrl) {
    baseImage.value = null
    return
  }

  const img = new Image()
  img.crossOrigin = 'anonymous'
  img.onload = () => {
    baseImage.value = img
  }
  img.onerror = (e) => {
    errorMessage.value = '无法显示图片，可能是跨域问题或图片不存在'
    mlog('Image load error:', e)
    baseImage.value = null
  }
  img.src = imageUrl
}

const loadMixFurnitureImage = (imageUrl: string) => {
  mlog('loadFurnitureImage', imageUrl)
  errorMessage.value = ''

  if (!imageUrl) {
    furnitureMixedImage.value = null
    return
  }

  const img = new Image()
  img.crossOrigin = 'anonymous'
  img.onload = () => {
    furnitureMixedImage.value = img
  }
  img.onerror = (e) => {
    errorMessage.value = '无法显示图片，可能是跨域问题或图片不存在'
    mlog('Image load error:', e)
    furnitureMixedImage.value = null
  }
  img.src = imageUrl
}

const imageConfig = computed(() => {
  if (!baseImage.value)
    return {}

  // 计算舞台四分之一区域的尺寸
  const quarterWidth = stageSize.width / 2
  const quarterHeight = stageSize.height / 2

  // 计算缩放比例以适应左上区域
  const scale = Math.min(quarterWidth / baseImage.value.width, quarterHeight / baseImage.value.height)

  return {
    image: baseImage.value,
    x: quarterWidth / 2,
    y: quarterHeight / 2,
    scaleX: scale,
    scaleY: scale,
    offsetX: baseImage.value.width / 2,
    offsetY: baseImage.value.height / 2,
    listening: true,
  }
})

const furnitureMixedImageConfig = computed(() => {
  if (!furnitureMixedImage.value)
    return {}

  // 计算舞台四分之一区域的尺寸
  const quarterWidth = stageSize.width / 2
  const quarterHeight = stageSize.height / 2

  // 计算缩放比例以适应右上区域
  const mixedScale = Math.min(quarterWidth / furnitureMixedImage.value.width, quarterHeight / furnitureMixedImage.value.height)

  return {
    image: furnitureMixedImage.value,
    x: quarterWidth + quarterWidth / 2, // 右上区域的x坐标
    y: quarterHeight / 2, // 右上区域的y坐标
    scaleX: mixedScale,
    scaleY: mixedScale,
    offsetX: furnitureMixedImage.value.width / 2,
    offsetY: furnitureMixedImage.value.height / 2,
    listening: true,
  }
})

const scaleFurniture = (id: string, scaleAmount: number) => {
  const furniture = furnitureImages.value.find(f => f.id === id)
  if (furniture) {
    const newScale = Math.max(0.1, Math.min(5, (furniture.scale?.x || 1) + scaleAmount))
    furniture.scale = { x: newScale, y: newScale }
  }
}
const deleteFurniture = (id: string) => {
  furnitureImages.value = furnitureImages.value.filter(item => item.id !== id)
  if (selectedFurnitureId.value === id)
    selectedFurnitureId.value = null
}

const handleKeyDown = (e: KeyboardEvent) => {
  if (e.key === 'Delete' && selectedFurnitureId.value)
    deleteFurniture(selectedFurnitureId.value)
}

// 处理画布缩放
const handleStageWheel = (e: any) => {
  e.evt.preventDefault()

  // 如果当前有选中的家具，则优先处理家具缩放
  if (selectedFurnitureId.value) {
    const scaleAmount = e.evt.deltaY > 0 ? -0.1 : 0.1
    scaleFurniture(selectedFurnitureId.value, scaleAmount)
    return
  }

  // 否则处理画布缩放
  const stage = stageRef.value.getStage()
  const pointer = stage.getPointerPosition()

  const oldScale = stageScale.value
  const scaleBy = 1.05
  const newScale = e.evt.deltaY > 0 ? oldScale / scaleBy : oldScale * scaleBy

  // 限制缩放范围
  const clampedScale = Math.max(0.1, Math.min(5, newScale))

  stageScale.value = clampedScale

  // 保持鼠标位置不变的缩放效果
  if (pointer) {
    const mousePointTo = {
      x: (pointer.x - stagePosition.x) / oldScale,
      y: (pointer.y - stagePosition.y) / oldScale,
    }

    stagePosition.x = pointer.x - mousePointTo.x * clampedScale
    stagePosition.y = pointer.y - mousePointTo.y * clampedScale
  }
}

// 处理画布拖拽开始
const handleStageDragStart = () => {
  // 只有在没有选中家具时才允许拖拽画布
  if (!selectedFurnitureId.value) {
    isDraggingStage.value = true
    const stage = stageRef.value.getStage()
    const pointer = stage.getPointerPosition()
    if (pointer) {
      lastPointerPosition.x = pointer.x
      lastPointerPosition.y = pointer.y
    }
  }
}

// 处理画布拖拽移动
const handleStageDragMove = () => {
  if (isDraggingStage.value) {
    const stage = stageRef.value.getStage()
    const pointer = stage.getPointerPosition()

    if (pointer) {
      const dx = pointer.x - lastPointerPosition.x
      const dy = pointer.y - lastPointerPosition.y

      stagePosition.x += dx
      stagePosition.y += dy

      lastPointerPosition.x = pointer.x
      lastPointerPosition.y = pointer.y
    }
  }
}

// 处理画布拖拽结束
const handleStageDragEnd = () => {
  isDraggingStage.value = false
}

const resetStageView = () => {
  stagePosition.x = 0
  stagePosition.y = 0
  stageScale.value = 1
}

// 防抖函数
const debounce = (func: Function, wait: number) => {
  let timeout: ReturnType<typeof setTimeout>
  return function (...args: any[]) {
    clearTimeout(timeout)
    timeout = setTimeout(() => func(...args), wait)
  }
}

// 更新舞台尺寸的函数
const updateStageSize = () => {
  // 获取 konva-container 的实际尺寸
  const container = document.querySelector('.konva-container')
  if (container) {
    // 减去 padding (20px * 2 = 40px)
    const containerWidth = container.clientWidth - 40
    const containerHeight = container.clientHeight - 40

    // 确保尺寸是正数
    if (containerWidth > 0 && containerHeight > 0) {
      // 设置最小尺寸以确保可见性
      stageSize.width = Math.max(containerWidth, 300)
      stageSize.height = Math.max(containerHeight, 200)
    }
  }
  else {
    // 如果无法获取容器尺寸，使用窗口尺寸作为后备
    stageSize.width = Math.max(window.innerWidth * 0.7, 300)
    stageSize.height = Math.max(window.innerHeight * 0.7, 200)
  }
}

const drawSent = (obj: any) => {
  mlog('drawSent', obj)
  if (obj && obj.fileBase64 && obj.fileBase64.length > 0 && obj.upType === 'base') {
    const firstImage = obj.fileBase64[0]
    if (typeof firstImage === 'string')
      loadBaseImage(firstImage)
    else if (firstImage && firstImage.url)
      loadBaseImage(firstImage.url)
  }
  else if (obj && obj.furnitureFileBase64 && obj.furnitureFileBase64.length > 0 && obj.upType === 'furniture') {
    const mixedFurnitureImage = obj.furnitureFileBase64[0]
    if (typeof mixedFurnitureImage === 'string')
      loadMixFurnitureImage(mixedFurnitureImage)
    else if (mixedFurnitureImage && mixedFurnitureImage.url)
      loadMixFurnitureImage(mixedFurnitureImage.url)
  }
  else if (obj && obj.action === 'clear') {
    baseImage.value = null
  }
  else if (obj && obj.action === 'clearFurniture') {
    furnitureMixedImage.value = null
  }
  else if (obj && obj.action === 'generatedImage') {
    loadBaseImage(obj.actData.imageUrl)
  }
  else if (obj && obj.action === 'preview') {
    mlog('handleCurrentChange', obj)
    furnitureImages.value = []
    selectedFurnitureId.value = null
    baseImage.value = null
    loadBaseImage(obj.url)
  }
  else if (obj && obj.action === 'result') {
    mlog('handleCurrentChange', obj)
  }
}

// 创建防抖版本的更新函数
const debouncedUpdateStageSize = debounce(updateStageSize, 300)

onMounted(() => {
  window.addEventListener('keydown', handleKeyDown)
  // 初始化舞台尺寸并添加窗口大小变化监听器
  updateStageSize()
  window.addEventListener('resize', debouncedUpdateStageSize)
})

onUnmounted(() => {
  window.removeEventListener('keydown', handleKeyDown)
  window.removeEventListener('resize', debouncedUpdateStageSize)
})
</script>

<template>
  <div class="flex h-full">
    <div class="h-full ">
      <aiSiderInput
        :button-disabled="false" @close="hcClose" @draw-sent="drawSent"
        @furniture-selected="handleFurnitureSelected" @request-canvas-image="requestCanvasImage"
      />
    </div>
    <main class="flex-1 overflow-hidden h-full">
      <div class="konva-container">
        <v-stage
          ref="stageRef"
          :config="{ ...stageSize, scaleX: stageScale, scaleY: stageScale, x: stagePosition.x, y: stagePosition.y }"
          class="konva-stage"
          @wheel="handleStageWheel"
          @mousedown="handleStageDragStart"
          @mousemove="handleStageDragMove"
          @mouseup="handleStageDragEnd"
          @mouseleave="handleStageDragEnd"
        >
          <v-layer>
            <v-image v-if="baseImage" :config="imageConfig" draggable="true" />
            <v-image v-if="furnitureMixedImage" :config="furnitureMixedImageConfig" draggable="true" />
            <!-- <v-image v-for="(config, index) in furnitureConfig" :key="index" :config="config"
                            draggable="true" /> -->
          </v-layer>
        </v-stage>
        <div v-if="errorMessage" class="error-message">
          {{ errorMessage }}
        </div>
        <button class="reset-button" @click="resetStageView">
          重置视图
        </button>
      </div>
    </main>
  </div>
</template>

<style scoped>
.konva-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 20px;
    height: 100%;
    width: 100%;
    background-color: #202020;
    background-image:
      linear-gradient(rgba(60, 60, 60, 0.2) 1px, transparent 1px),
      linear-gradient(90deg, rgba(60, 60, 60, 0.2) 1px, transparent 1px);
    background-size: 20px 20px;
}

.konva-stage {
    border: 1px solid #e0e0e0;
    border-radius: 4px;
    background-color: #000000;
}

.error-message {
    margin-top: 15px;
    color: #ff4444;
    font-size: 14px;
}

.reset-view-btn {
    margin-top: 10px;
    padding: 5px 10px;
    background-color: #4a4a4a;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

.reset-view-btn:hover {
    background-color: #5a5a5a;
}
</style>
